/**
 * 
 */
package org.log4jconfig.xml.editor.hyperlink;

import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.text.rules.SimpleStructuredTypedRegion;
import org.eclipse.wst.sse.core.utils.StringUtils;
import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
import org.eclipse.wst.xml.core.internal.parser.regions.AttributeNameRegion;
import org.eclipse.wst.xml.core.internal.parser.regions.AttributeValueRegion;
import org.log4jconfig.xml.editor.utils.Logger;
import org.log4jconfig.xml.editor.utils.StructuredDocumentRegionUtils;

/**
 * @author Xi
 * 
 */
@SuppressWarnings("restriction")
public class AppenderRefValueHyperlinkDetector extends AbstractHyperlinkDetector {

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.jface.text.hyperlink.IHyperlinkDetector#detectHyperlinks(
	 * org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion,
	 * boolean)
	 */
	public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
		try {
			IStructuredDocumentRegion structuredDocumentRegion = ContentAssistUtils.getStructuredDocumentRegion(
					textViewer, region.getOffset());
			ITextRegion attributeValueRegion = structuredDocumentRegion.getRegionAtCharacterOffset(region.getOffset());
			if (attributeValueRegion instanceof AttributeValueRegion) {
				String tagName = StructuredDocumentRegionUtils.extractTagName(structuredDocumentRegion);
				String attributeName = StructuredDocumentRegionUtils.extractAttributeName(structuredDocumentRegion,
						(AttributeValueRegion) attributeValueRegion);
				if ("appender-ref".equals(tagName) && "ref".equals(attributeName)) {
					String attributeValue = StructuredDocumentRegionUtils.extractAttributeValue(
							structuredDocumentRegion, region.getOffset());
					IStructuredDocumentRegion target = findAppenderStructuredRegion(structuredDocumentRegion
							.getParentDocument(), attributeValue);
					if (target != null) {
						IRegion hyperlinkRegion = new SimpleStructuredTypedRegion(structuredDocumentRegion
								.getStartOffset()
								+ attributeValueRegion.getStart() + 1, attributeValue.length(), attributeValueRegion
								.getType());
						return new IHyperlink[] { new AppenderElementHyperlink(hyperlinkRegion, target, textViewer) };
					} else {
						Logger.info("Unable to find any <appender> element with name " + attributeValue
								+ " in current document");
					}
				}
			}

		} catch (Exception e) {
			Logger.error("Failed to detect hyperlink: " + e.getMessage(), e);
		}
		return null;
	}

	private IStructuredDocumentRegion findAppenderStructuredRegion(IStructuredDocument parentDocument,
			String targetAppenderName) {
		IStructuredDocumentRegion[] regions = parentDocument.getStructuredDocumentRegions();
		for (IStructuredDocumentRegion region : regions) {
			String elementName = StructuredDocumentRegionUtils.extractTagName(region);
			if ("appender".equals(elementName)) {
				if (targetAppenderName.equals(getAppenderName(region))) {
					return region;
				}
			}
		}

		return null;
	}

	private String getAppenderName(IStructuredDocumentRegion structuredDocumentRegion) {
		int index = 0;
		ITextRegion region = structuredDocumentRegion.getFirstRegion();
		while (!region.equals(structuredDocumentRegion.getLastRegion())) {
			if (region instanceof AttributeNameRegion
					&& "name".equals(StringUtils.strip(structuredDocumentRegion.getFullText(region)))) {
				ITextRegion attributeValueRegion = structuredDocumentRegion.getRegions().get(index + 2);
				if (attributeValueRegion instanceof AttributeValueRegion) {
					return StringUtils.strip(structuredDocumentRegion.getText(attributeValueRegion));
				}
			}

			index++;
			region = structuredDocumentRegion.getRegions().get(index);
		}
		return StringUtils.strip(structuredDocumentRegion.getText(region));
	}

}
